package org.yelongframework.model.support.service.base;

import java.util.Objects;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.yelongframework.lang.Nullable;
import org.yelongframework.model.configuration.ModelConfiguration;
import org.yelongframework.model.service.ModelService;
import org.yelongframework.model.service.SqlModelService;
import org.yelongframework.model.service.support.supplier.SqlModelServiceSupplier;
import org.yelongframework.sql.dialect.SqlDialect;
import org.yelongframework.sql.fragment.condition.combination.CombinationConditionSqlFragment;
import org.yelongframework.sql.fragment.condition.simple.SimpleConditionSqlFragment;
import org.yelongframework.sql.fragment.order.OrderSqlFragment;
import org.yelongframework.sql.store.SqlStore;

/**
 * 基础的模型服务，提供一些公用的方法
 * 
 * @since 1.0.0
 */
public abstract class BaseModelService implements SqlModelServiceSupplier {

	private static final Logger logger = LoggerFactory.getLogger(BaseModelService.class);

	// ==================================================SQL片段==================================================

	// ==================================================组合条件==================================================

	/**
	 * @return 组合条件
	 */
	public CombinationConditionSqlFragment createCombinationConditionSqlFragment() {
		return createCombinationConditionSqlFragment(getModelService());
	}

	/**
	 * @param modelService 模型服务
	 * @return 组合条件
	 */
	public CombinationConditionSqlFragment createCombinationConditionSqlFragment(ModelService modelService) {
		return modelService.getModelConfiguration().getModelSqlFragmentFactory().getSqlFragmentFactory()
				.createCombinationConditionSqlFragment();
	}

	// ==================================================简单条件==================================================

	/**
	 * @param conditionSqlFragment 条件sql ： username = ?
	 * @param params               条件的参数
	 * @return 简单条件
	 */
	public SimpleConditionSqlFragment createSimpleConditionSqlFragment(String conditionSqlFragment, Object... params) {
		return createSimpleConditionSqlFragment(getModelService(), conditionSqlFragment, params);
	}

	/**
	 * @param modelService         模型服务
	 * @param conditionSqlFragment 条件sql ： username = ?
	 * @param params               条件的参数
	 * @return 简单条件
	 */
	public SimpleConditionSqlFragment createSimpleConditionSqlFragment(ModelService modelService,
			String conditionSqlFragment, Object... params) {
		return modelService.getModelConfiguration().getModelSqlFragmentFactory().getSqlFragmentFactory()
				.createSimpleConditionSqlFragment(conditionSqlFragment, params);
	}

	// ==================================================order==================================================

	/**
	 * @return 排序
	 */
	public OrderSqlFragment createOrderSqlFragment() {
		return createOrderSqlFragment(getModelService());
	}

	/**
	 * @param modelService 模型服务
	 * @return 排序
	 */
	public OrderSqlFragment createOrderSqlFragment(ModelService modelService) {
		return modelService.getModelConfiguration().getModelSqlFragmentFactory().getSqlFragmentFactory()
				.createOrderSqlFragment();
	}

	// ==================================================SqlStore==================================================

	/**
	 * 获取SQL存储里面的SQL语句
	 * 
	 * @param namespace 命名空间
	 * @param sqlName   SQL名称
	 * @return SQL语句
	 */
	@Nullable
	public String getSqlStoreSql(String sqlName) {
		String dialectName = getDialect().getName();
		return getSqlStoreSql(sqlName, dialectName);
	}

	/**
	 * 获取SQL存储里面的SQL语句
	 * 
	 * @param namespace    命名空间
	 * @param sqlName      SQL名称
	 * @param databaseName 数据库名称
	 * @return SQL语句
	 * @throws IllegalArgumentException 没有找到SQL
	 */
	@Nullable
	public String getSqlStoreSql(String sqlName, @Nullable String databaseName) {
		SqlStore sqlStore = Objects.requireNonNull(getSqlStore(), "不支持使用SqlStore，请重写获取SqlStore的方法");
		String sqlStoreNamespace = getDefaultSqlStoreNamespace();
		logger.info("在SqlStore中寻找命名空间" + sqlStoreNamespace + "下名称为" + sqlName + "，数据库名称为" + databaseName + "的SQL语句");
		String sql = sqlStore.getSql(sqlStoreNamespace, sqlName, databaseName);
		if (StringUtils.isBlank(sql)) {
			sql = sqlStore.getSql(sqlStoreNamespace, sqlName);
		}
		if (StringUtils.isBlank(sql)) {
			throw new IllegalArgumentException(
					"没有在SqlStore中找到命名空间" + sqlStoreNamespace + "下名称为" + sqlName + "，数据库名称为" + databaseName + "的SQL语句");
		}
		return sql;
	}

	/**
	 * @return 默认的SQL存储命名空间。默认为当前实现类的类名称
	 */
	protected String getDefaultSqlStoreNamespace() {
		return getClass().getSimpleName();
	}

	// ==================================================support==================================================

	/**
	 * @return 模型服务
	 */
	@Override
	public abstract SqlModelService getModelService();

	/**
	 * @return 模型配置
	 */
	public ModelConfiguration getModelConfiguration() {
		return getModelService().getModelConfiguration();
	}

	/**
	 * @return 数据库方言
	 */
	public SqlDialect getDialect() {
		return getModelConfiguration().getDialect();
	}

	/**
	 * @return SQL存储
	 */
	@Nullable
	public abstract SqlStore getSqlStore();

}
